<script setup lang="ts">
import { onMounted, ref, reactive, h } from "vue";
import { DynamicTable } from "@/components/DynamicTable";
import { PaginationConfig, TableColumn } from "@/components/DynamicTable/types";
import DynamicForm from "@/components/DynamicForm/index.vue";
import type { DynamicFormInstance } from "@/components/DynamicForm/types";
import { FormItemConfig } from "@/components/DynamicForm/types";
import {
  ElMessage,
  ElMessageBox,
  ElTag,
  ElDialog,
  ElDescriptions,
  ElSwitch,
} from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import {
  uploadGadget,
  addGadget,
  getGadgetList,
  getGadgetDetail,
  updateGadget,
  toggleGadget,
  deleteGadget,
} from "../servers";

const pagination = reactive<PaginationConfig>({
  currentPage: 1,
  pageSize: 20,
  total: 0,
  pageSizes: [10, 20, 50, 100],
  layout: "total, sizes, prev, pager, next",
  background: true,
});

const gadgetList = ref([]);
const loading = ref(false);
const searchFormRef = ref<DynamicFormInstance>();

// 上传相关
const uploadDialogVisible = ref(false);
const fileList = ref([]);
const uploadForm = reactive({
  chain_name: "",
  gadget_type: "",
  uploaded_by: "admin",
});

// 新增相关
const addDialogVisible = ref(false);
const addForm = reactive({
  chain_name: "",
  gadget_type: "",
  component_name: "",
  component_version: "",
  entry_class: "",
  chain_classes: "",
  can_exec_command: false,
  can_jndi_inject: false,
  can_dns_query: false,
  can_file_read: false,
  can_file_write: false,
  can_http_request: false,
  jdk_version: "",
  os_support: "all",
  dependencies: "",
  cve_list: "",
  description: "",
  risk_level: "",
  tags: "",
});

// 编辑相关
const editDialogVisible = ref(false);
const editForm = reactive({
  id: null,
  chain_name: "",
  description: "",
  can_exec_command: false,
  can_jndi_inject: false,
  can_dns_query: false,
  can_file_read: false,
  can_file_write: false,
  can_http_request: false,
  jdk_version: "",
});

// 详情相关
const detailDialogVisible = ref(false);
const detailData = ref(null);

// 搜索表单
const searchFormData = reactive({
  chain_name: "",
  gadget_type: "",
  is_available: "",
});

const searchFormConfig: FormItemConfig[] = [
  {
    key: "chain_name",
    name: "关键词",
    type: "input",
    placeholder: "搜索链名称",
    params: {
      clearable: true,
      style: { width: "200px" },
    },
  },
  {
    key: "gadget_type",
    name: "类型",
    type: "select",
    placeholder: "选择类型",
    options: [
      { label: "全部", value: "" },
      { label: "Commons Collections", value: "commons-collections" },
      { label: "Commons Beanutils", value: "commons-beanutils" },
      { label: "Spring", value: "spring" },
      { label: "Fastjson", value: "fastjson" },
      { label: "其他", value: "other" },
    ],
    params: {
      clearable: true,
      style: { width: "200px" },
      showPlaceholder: false,
    },
  },
  {
    key: "is_available",
    name: "状态",
    type: "select",
    placeholder: "选择状态",
    options: [
      { label: "全部", value: "" },
      { label: "可用", value: "true" },
      { label: "禁用", value: "false" },
    ],
    params: {
      clearable: true,
      style: { width: "200px" },
      showPlaceholder: false,
    },
  },
];

const columns = ref<TableColumn[]>([
  {
    label: "ID",
    prop: "id",
    width: 60,
    show: true,
  },
  {
    label: "链名称",
    prop: "chain_name",
    show: true,
  },
  {
    label: "类型",
    prop: "gadget_type",
    show: true,
    render: (row) => {
      const typeMap = {
        "commons-collections": "Commons Collections",
        "commons-beanutils": "Commons Beanutils",
        spring: "Spring",
        fastjson: "Fastjson",
        other: "其他",
      };
      return typeMap[row.gadget_type] || row.gadget_type;
    },
  },
  {
    label: "能力",
    prop: "capabilities",
    show: true,
    slot: "capabilities",
  },
  {
    label: "文件大小",
    prop: "jar_size",
    show: true,
    render: (row) => {
      if (!row.jar_size) return "-";
      const bytes = row.jar_size;
      if (bytes < 1024) return bytes + " B";
      if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB";
      return (bytes / 1024 / 1024).toFixed(2) + " MB";
    },
  },
  {
    label: "状态",
    prop: "is_available",
    width: 100,
    show: true,
    slot: "status",
  },
  {
    label: "上传时间",
    prop: "uploaded_at",
    width: 160,
    show: true,
  },
  {
    label: "标签",
    prop: "tags",
    width: 200,
    show: true,
    slot: "tags",
  },
  {
    label: "操作",
    prop: "action",
    width: 220,
    show: true,
    slot: "action",
    fixed: "right",
  },
]);

// 获取列表数据
const fetchGadgetList = async () => {
  loading.value = true;
  try {
    const params: any = {
      page: pagination.currentPage,
      per_page: pagination.pageSize,
      ...searchFormData,
    };
    // 移除空值
    Object.keys(params).forEach((key) => {
      if (
        params[key] === "" ||
        params[key] === null ||
        params[key] === undefined
      ) {
        delete params[key];
      }
    });
    const { data } = await getGadgetList(params);
    gadgetList.value = data.gadgets || [];
    pagination.total = data.total || 0;
  } catch (error) {
    ElMessage.error("获取Gadget列表失败");
  } finally {
    loading.value = false;
  }
};

const handleSearch = (value: any) => {
  searchFormData.chain_name = value.chain_name || "";
  searchFormData.gadget_type = value.gadget_type || "";
  searchFormData.is_available = value.is_available || "";
  pagination.currentPage = 1;
  fetchGadgetList();
};

const handleSearchReset = () => {
  searchFormRef.value?.resetFields();
  searchFormData.chain_name = "";
  searchFormData.gadget_type = "";
  searchFormData.is_available = "";
  pagination.currentPage = 1;
  fetchGadgetList();
};

const handlePageChange = (page: number) => {
  pagination.currentPage = page;
  fetchGadgetList();
};

const handleSizeChange = (size: number) => {
  pagination.pageSize = size;
  pagination.currentPage = 1;
  fetchGadgetList();
};

// 上传相关
const handleUpload = () => {
  uploadDialogVisible.value = true;
};

const beforeUpload = (file: any, fileListRef: any) => {
  // fileListRef 是更新后的文件列表
  fileList.value = fileListRef;
  if (!file.raw || !file.raw.name.endsWith(".jar")) {
    if (file.raw) {
      ElMessage.error("只能上传.jar文件");
      // 移除非 .jar 文件
      fileList.value = fileList.value.filter(
        (f: any) => f.raw && f.raw.name.endsWith(".jar")
      );
    }
  }
};

const submitUpload = async () => {
  if (!fileList.value.length) {
    ElMessage.error("请选择JAR文件");
    return;
  }
  if (!uploadForm.chain_name) {
    ElMessage.error("请输入链名称");
    return;
  }
  if (!uploadForm.gadget_type) {
    ElMessage.error("请选择链类型");
    return;
  }

  const formData = new FormData();
  // 获取文件对象，Element Plus会自动处理
  const file = fileList.value[0].raw || fileList.value[0];
  formData.append("file", file);
  formData.append("chain_name", uploadForm.chain_name);
  formData.append("gadget_type", uploadForm.gadget_type);
  if (uploadForm.uploaded_by) {
    formData.append("uploaded_by", uploadForm.uploaded_by);
  }

  try {
    await uploadGadget(formData);
    ElMessage.success("上传成功");
    uploadDialogVisible.value = false;
    resetUploadForm();
    fetchGadgetList();
  } catch (error: any) {
    ElMessage.error(error.message || "上传失败");
  }
};

const resetUploadForm = () => {
  fileList.value = [];
  uploadForm.chain_name = "";
  uploadForm.gadget_type = "";
  uploadForm.uploaded_by = "admin";
};

// 新增
const handleAdd = () => {
  addDialogVisible.value = true;
};

const submitAdd = async () => {
  if (!addForm.chain_name || !addForm.gadget_type) {
    ElMessage.error("请输入链名称和类型");
    return;
  }

  try {
    const params: any = { ...addForm };
    // 移除空值和 false
    Object.keys(params).forEach((key) => {
      if (
        params[key] === "" ||
        params[key] === null ||
        params[key] === undefined ||
        params[key] === false
      ) {
        delete params[key];
      }
    });
    await addGadget(params);
    ElMessage.success("新增成功");
    addDialogVisible.value = false;
    resetAddForm();
    fetchGadgetList();
  } catch (error: any) {
    ElMessage.error(error.message || "新增失败");
  }
};

const resetAddForm = () => {
  Object.keys(addForm).forEach((key) => {
    if (typeof addForm[key] === "boolean") {
      addForm[key] = false;
    } else if (key === "os_support") {
      addForm[key] = "all";
    } else {
      addForm[key] = "";
    }
  });
};

// 查看详情
const handleViewDetail = async (row: any) => {
  try {
    const { data } = await getGadgetDetail({ gadget_id: row.id });
    detailData.value = data;
    detailDialogVisible.value = true;
  } catch (error) {
    ElMessage.error("获取详情失败");
  }
};

// 编辑
const handleEdit = (row: any) => {
  editForm.id = row.id;
  editForm.chain_name = row.chain_name;
  editForm.description = row.description || "";
  editForm.can_exec_command = row.can_exec_command;
  editForm.can_jndi_inject = row.can_jndi_inject;
  editForm.can_dns_query = row.can_dns_query;
  editForm.can_file_read = row.can_file_read;
  editForm.can_file_write = row.can_file_write;
  editForm.can_http_request = row.can_http_request;
  editForm.jdk_version = row.jdk_version || "";
  editDialogVisible.value = true;
};

const handleSaveEdit = async () => {
  try {
    await updateGadget({
      gadget_id: editForm.id,
      chain_name: editForm.chain_name,
      description: editForm.description,
      can_exec_command: editForm.can_exec_command,
      can_jndi_inject: editForm.can_jndi_inject,
      can_dns_query: editForm.can_dns_query,
      can_file_read: editForm.can_file_read,
      can_file_write: editForm.can_file_write,
      can_http_request: editForm.can_http_request,
      jdk_version: editForm.jdk_version,
    });
    ElMessage.success("更新成功");
    editDialogVisible.value = false;
    fetchGadgetList();
  } catch (error) {
    ElMessage.error("更新失败");
  }
};

// 启用/禁用
const handleToggle = (row: any) => {
  const newStatus = !row.is_available;
  const action = newStatus ? "启用" : "禁用";

  ElMessageBox.confirm(`确定要${action} ${row.chain_name}?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      try {
        await toggleGadget({
          gadget_id: row.id,
          is_available: newStatus,
        });
        // 更新本地状态
        row.is_available = newStatus;
        ElMessage.success(`${action}成功`);
        // 刷新列表确保数据同步
        fetchGadgetList();
      } catch (error) {
        ElMessage.error("操作失败");
      }
    })
    .catch(() => {
      // 用户取消，不做任何操作，switch会保持原状态
    });
};

// 删除
const handleDelete = (row: any) => {
  ElMessageBox.confirm(`确定删除 ${row.chain_name}?`, "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      try {
        await deleteGadget({ gadget_ids: [row.id], delete_file: true });
        ElMessage.success("删除成功");
        fetchGadgetList();
      } catch (error) {
        ElMessage.error("删除失败");
      }
    })
    .catch(() => {});
};

onMounted(() => {
  fetchGadgetList();
});
</script>

<template>
  <div>
    <!-- 搜索表单 -->
    <el-card shadow="never">
      <div class="search-form-container">
        <DynamicForm
          ref="searchFormRef"
          v-model="searchFormData"
          :form-config="searchFormConfig"
          :gutter="16"
          label-width="80px"
          type="search"
          @search="handleSearch"
          @reset="handleSearchReset"
        />
      </div>
    </el-card>

    <div style="height: 10px"></div>

    <el-card>
      <DynamicTable
        :pagination="pagination"
        :columns="columns"
        :data="gadgetList"
        :loading="loading"
        @current-page-change="handlePageChange"
        @size-change="handleSizeChange"
      >
        <template #toolbar-left>
          <el-button type="primary" @click="handleUpload">
            <el-icon :size="16"><Plus /></el-icon>
            <span style="margin-left: 4px">上传JAR包</span>
          </el-button>
          <el-button type="success" @click="handleAdd">
            <el-icon :size="16"><Plus /></el-icon>
            <span style="margin-left: 4px">新增Gadget链</span>
          </el-button>
        </template>

        <template #capabilities="{ row }">
          <el-tag
            v-if="row.can_exec_command"
            size="small"
            type="danger"
            style="margin-right: 4px"
            >CMD</el-tag
          >
          <el-tag
            v-if="row.can_jndi_inject"
            size="small"
            type="warning"
            style="margin-right: 4px"
            >JNDI</el-tag
          >
          <el-tag
            v-if="row.can_dns_query"
            size="small"
            type="info"
            style="margin-right: 4px"
            >DNS</el-tag
          >
          <el-tag
            v-if="row.can_file_read"
            size="small"
            style="margin-right: 4px"
            >READ</el-tag
          >
          <el-tag
            v-if="row.can_file_write"
            size="small"
            style="margin-right: 4px"
            >WRITE</el-tag
          >
          <el-tag
            v-if="row.can_http_request"
            size="small"
            type="success"
            style="margin-right: 4px"
            >HTTP</el-tag
          >
        </template>

        <template #status="{ row }">
          <el-switch
            :model-value="row.is_available"
            @change="handleToggle(row)"
          />
        </template>

        <template #tags="{ row }">
          <el-tag
            v-for="tag in row.tags"
            :key="tag"
            size="small"
            style="margin-right: 4px"
            >{{ tag }}</el-tag
          >
          <el-tag
            v-if="!row.tags || row.tags.length === 0"
            size="small"
            type="info"
            >无</el-tag
          >
        </template>

        <template #action="{ row }">
          <el-button type="primary" size="small" @click="handleViewDetail(row)"
            >详情</el-button
          >
          <el-button type="warning" size="small" @click="handleEdit(row)"
            >编辑</el-button
          >
          <el-button type="danger" size="small" @click="handleDelete(row)"
            >删除</el-button
          >
        </template>
      </DynamicTable>
    </el-card>

    <!-- 上传弹窗 -->
    <el-dialog v-model="uploadDialogVisible" title="上传Gadget链" width="600px">
      <el-form :model="uploadForm" label-width="120px">
        <el-form-item label="JAR文件" required>
          <el-upload
            ref="uploadRef"
            :auto-upload="false"
            :on-change="beforeUpload"
            :file-list="fileList"
            accept=".jar"
            :limit="1"
          >
            <el-button type="primary">选择文件</el-button>
            <template #tip>
              <div class="el-upload__tip">支持.jar文件</div>
            </template>
          </el-upload>
        </el-form-item>

        <el-form-item label="链名称" required>
          <el-input
            v-model="uploadForm.chain_name"
            placeholder="如: CommonsCollections1"
          />
        </el-form-item>

        <el-form-item label="链类型" required>
          <el-select
            v-model="uploadForm.gadget_type"
            placeholder="选择类型"
            style="width: 100%"
          >
            <el-option
              label="Commons Collections"
              value="commons-collections"
            />
            <el-option label="Commons Beanutils" value="commons-beanutils" />
            <el-option label="Spring" value="spring" />
            <el-option label="Fastjson" value="fastjson" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="uploadDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitUpload">确定上传</el-button>
      </template>
    </el-dialog>

    <!-- 编辑弹窗 -->
    <el-dialog v-model="editDialogVisible" title="编辑Gadget链" width="600px">
      <el-form :model="editForm" label-width="120px">
        <el-form-item label="链名称">
          <el-input v-model="editForm.chain_name" />
        </el-form-item>

        <el-form-item label="支持能力">
          <el-checkbox v-model="editForm.can_exec_command"
            >命令执行</el-checkbox
          >
          <el-checkbox v-model="editForm.can_jndi_inject">JNDI注入</el-checkbox>
          <el-checkbox v-model="editForm.can_dns_query">DNS查询</el-checkbox>
          <el-checkbox v-model="editForm.can_file_read">文件读取</el-checkbox>
          <el-checkbox v-model="editForm.can_file_write">文件写入</el-checkbox>
          <el-checkbox v-model="editForm.can_http_request"
            >HTTP请求</el-checkbox
          >
        </el-form-item>

        <el-form-item label="JDK版本">
          <el-input v-model="editForm.jdk_version" />
        </el-form-item>

        <el-form-item label="描述">
          <el-input v-model="editForm.description" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="editDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSaveEdit">确定</el-button>
      </template>
    </el-dialog>

    <!-- 新增弹窗 -->
    <el-dialog v-model="addDialogVisible" title="新增Gadget链" width="800px">
      <el-form :model="addForm" label-width="140px">
        <el-form-item label="链名称" required>
          <el-input
            v-model="addForm.chain_name"
            placeholder="如: CommonsCollections1"
          />
        </el-form-item>

        <el-form-item label="链类型" required>
          <el-select
            v-model="addForm.gadget_type"
            placeholder="选择类型"
            style="width: 100%"
          >
            <el-option
              label="Commons Collections"
              value="commons-collections"
            />
            <el-option label="Commons Beanutils" value="commons-beanutils" />
            <el-option label="Spring" value="spring" />
            <el-option label="Fastjson" value="fastjson" />
            <el-option label="其他" value="other" />
          </el-select>
        </el-form-item>

        <el-form-item label="组件名称">
          <el-input
            v-model="addForm.component_name"
            placeholder="如: commons-collections"
          />
        </el-form-item>

        <el-form-item label="组件版本">
          <el-input
            v-model="addForm.component_version"
            placeholder="如: 3.2.1"
          />
        </el-form-item>

        <el-form-item label="入口类">
          <el-input
            v-model="addForm.entry_class"
            placeholder="如: org.apache.commons..."
          />
        </el-form-item>

        <el-form-item label="链类列表">
          <el-input
            v-model="addForm.chain_classes"
            placeholder="逗号分隔，如: InvokerTransformer,ChainedTransformer"
          />
        </el-form-item>

        <el-form-item label="JDK版本">
          <el-input v-model="addForm.jdk_version" placeholder="如: 1.7, 1.8" />
        </el-form-item>

        <el-form-item label="操作系统">
          <el-select v-model="addForm.os_support" style="width: 100%">
            <el-option label="全部" value="all" />
            <el-option label="Windows" value="windows" />
            <el-option label="Linux" value="linux" />
          </el-select>
        </el-form-item>

        <el-form-item label="支持能力">
          <el-checkbox v-model="addForm.can_exec_command">命令执行</el-checkbox>
          <el-checkbox v-model="addForm.can_jndi_inject">JNDI注入</el-checkbox>
          <el-checkbox v-model="addForm.can_dns_query">DNS查询</el-checkbox>
          <el-checkbox v-model="addForm.can_file_read">文件读取</el-checkbox>
          <el-checkbox v-model="addForm.can_file_write">文件写入</el-checkbox>
          <el-checkbox v-model="addForm.can_http_request">HTTP请求</el-checkbox>
        </el-form-item>

        <el-form-item label="依赖ID">
          <el-input
            v-model="addForm.dependencies"
            placeholder="逗号分隔的JAR ID，如: 1,2,3"
          />
        </el-form-item>

        <el-form-item label="CVE列表">
          <el-input
            v-model="addForm.cve_list"
            placeholder="逗号分隔，如: CVE-2015-6420,CVE-2015-7501"
          />
        </el-form-item>

        <el-form-item label="风险等级">
          <el-select v-model="addForm.risk_level" style="width: 100%">
            <el-option label="严重" value="critical" />
            <el-option label="高危" value="high" />
            <el-option label="中危" value="medium" />
            <el-option label="低危" value="low" />
          </el-select>
        </el-form-item>

        <el-form-item label="标签">
          <el-input
            v-model="addForm.tags"
            placeholder="逗号分隔，如: Gadget,反序列化"
          />
        </el-form-item>

        <el-form-item label="描述">
          <el-input
            v-model="addForm.description"
            type="textarea"
            :rows="3"
            placeholder="输入描述信息"
          />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="addDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitAdd">确定</el-button>
      </template>
    </el-dialog>

    <!-- 详情弹窗 -->
    <el-dialog v-model="detailDialogVisible" title="Gadget链详情" width="800px">
      <el-descriptions v-if="detailData" :column="2" border>
        <el-descriptions-item label="ID">{{
          detailData.id
        }}</el-descriptions-item>
        <el-descriptions-item label="链名称">{{
          detailData.chain_name
        }}</el-descriptions-item>
        <el-descriptions-item label="链类型">{{
          detailData.gadget_type
        }}</el-descriptions-item>
        <el-descriptions-item label="JAR文件名">{{
          detailData.jar_name
        }}</el-descriptions-item>
        <el-descriptions-item label="文件大小"
          >{{ detailData.jar_size }} 字节</el-descriptions-item
        >
        <el-descriptions-item label="MD5">{{
          detailData.jar_md5
        }}</el-descriptions-item>
        <el-descriptions-item label="组件名">{{
          detailData.component_name
        }}</el-descriptions-item>
        <el-descriptions-item label="组件版本">{{
          detailData.component_version
        }}</el-descriptions-item>
        <el-descriptions-item label="JDK版本">{{
          detailData.jdk_version
        }}</el-descriptions-item>
        <el-descriptions-item label="操作系统">{{
          detailData.os_support
        }}</el-descriptions-item>
        <el-descriptions-item label="上传人">{{
          detailData.uploaded_by
        }}</el-descriptions-item>
        <el-descriptions-item label="上传时间">{{
          detailData.uploaded_at
        }}</el-descriptions-item>
        <el-descriptions-item label="标签" :span="2">
          <el-tag
            v-for="tag in detailData.tags"
            :key="tag"
            size="small"
            style="margin-right: 4px"
            >{{ tag }}</el-tag
          >
          <el-tag
            v-if="!detailData.tags || detailData.tags.length === 0"
            size="small"
            type="info"
            >无标签</el-tag
          >
        </el-descriptions-item>
        <el-descriptions-item label="状态" :span="2">
          <el-tag :type="detailData.is_available ? 'success' : 'danger'">
            {{ detailData.is_available ? "可用" : "禁用" }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="描述" :span="2">{{
          detailData.description
        }}</el-descriptions-item>
      </el-descriptions>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
.search-form-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
</style>
